﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Input;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http.Headers;

namespace G.Net
{

    public class RequestResult
    {
        public RequestResult(System.Net.Http.HttpRequestException ex, string result)
        {
            this.Exception = ex;
            this.Result = result;
        }
        /// <summary>
        /// 如果请求的过程中没有出现异常，那么Exception为空
        /// </summary>
        public System.Net.Http.HttpRequestException Exception { get; set; }

        /// <summary>
        /// 请求成功后服务端返回的字符串信息
        /// </summary>
        public string Result { get; set; }
    }

    public abstract class HttpRequest : IHttpRequest
    {
        /// <summary>
        /// The uri the request goes to.
        /// </summary>
        protected string Uri;

        /// <summary>
        /// Initializes a new instance of <see cref="HttpRequest"/> with the specified <paramref name="uri"/>.
        /// </summary>
        /// <param name="uri">The uri the request goes to.</param>
        protected HttpRequest(string uri)
        {
            this.Uri = uri;
        }

        public virtual async Task<RequestResult> RequestAsync()
        {
            //Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3
            string url = ConstructUri();
            System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
            AppendHeaders(client.DefaultRequestHeaders);
            PrepareRequest(client);

            if (Method == System.Net.Http.HttpMethod.Post)
            {
                System.Net.Http.HttpContent content = WriteBody();
                if (content == null)
                    content = new System.Net.Http.StringContent(string.Empty);
                if (!string.IsNullOrEmpty(ContentType))
                {
                    content.Headers.ContentType = new MediaTypeHeaderValue(this.ContentType);
                }
                try
                {
                    var manager = await client.PostAsync(url, content);
                    string str = await manager.Content.ReadAsStringAsync();
                    if (manager.IsSuccessStatusCode)
                        return new RequestResult(null, str);
                    else
                        return new RequestResult(new System.Net.Http.HttpRequestException(manager.ReasonPhrase), str);
                }
                catch (System.Net.Http.HttpRequestException ex)
                {
                    return new RequestResult(ex, ex.Message);
                }

            }
            else if (Method == System.Net.Http.HttpMethod.Get)
            {
                try
                {
                    var message = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url);
                    var response = await client.SendAsync(message);
                    var str = await response.Content.ReadAsStringAsync();
                    return new RequestResult(null, str);
                }
                catch (System.Net.Http.HttpRequestException ex)
                {
                    return new RequestResult(ex, ex.Message);
                }
            }
            else
                throw new InvalidOperationException("除了Get和Post，不能使用其他方法");
        }

        /// <summary>
        /// When overriden in derived classes, constructs the final request uri based on relevent conditions.
        /// </summary>
        /// <returns>The final request uri constucted.</returns>
        protected virtual string ConstructUri()
        {
            return Uri;
        }

        /// <summary>
        /// When overridden in derived classes, appends HTTP headers into the request.
        /// </summary>
        /// <param name="headers">The web header collection object.</param>
        protected virtual void AppendHeaders(HttpRequestHeaders headers)
        {
            // Nothing to do.
        }

        /// <summary>
        /// When overridden in derived classes, sets additional request arguments on the web request object.
        /// </summary>
        /// <param name="webRequest">The web request object.</param>
        protected virtual void PrepareRequest(System.Net.Http.HttpClient webRequest)
        {
            // Nothing to do.
        }

        /// <summary>
        /// When overridden in derived classes, writes data into the request stream.
        /// <remarks>HTTP GET type request is not supported.</remarks>
        /// </summary>
        /// <param name="reqStream">The request stream object.</param>
        protected virtual System.Net.Http.HttpContent WriteBody()
        {
            return null;
            // Nothing to do. 
        }

        /// <summary>
        /// Retrieves the response from the request.
        /// </summary>
        /// <param name="webResponse"></param>
        /// <returns>The server response string(UTF8 decoded).</returns>
        protected virtual string RetrieveResponse(WebResponse webResponse)
        {
            var respContent = string.Empty;
            var respStream = webResponse.GetResponseStream();
            using (StreamReader reader = new StreamReader(respStream, Encoding.UTF8))
            {
                respContent = reader.ReadToEnd();
            }
            webResponse.Dispose();

            return respContent;
        }

        /// <summary>
        /// Gets or sets the HTTP method of the request.(i.e: POST, GET etc.)
        /// </summary>
        protected virtual System.Net.Http.HttpMethod Method
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the content type of the request.(i.e: text/plain etc.)
        /// </summary>
        protected virtual string ContentType
        {
            get;
            set;
        }
    }
}
